package com.stone.framework.basic.param.service.impl;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.stone.framework.basic.param.entity.SystemParam;
import com.stone.framework.basic.param.repository.SystemParamRepository;
import com.stone.framework.basic.param.service.SystemParamService;
import com.stone.framework.core.cache.BasicConstant;
import com.stone.framework.core.exception.BusinessException;
import com.stone.framework.core.util.Beans;
import com.stone.framework.message.basic.param.SystemParamPageReqBody;
import com.stone.framework.message.basic.param.SystemParamPageResBody;
import com.stone.framework.message.basic.param.SystemParamReqBody;

@Service
@Transactional(readOnly = true)
public class SystemParamServiceImpl implements SystemParamService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SystemParamServiceImpl.class);

    @Autowired
    private SystemParamRepository systemParamRepository;

    @Override
    public Page<SystemParamPageResBody> queryPage(SystemParamPageReqBody reqBody, Pageable pageable) {
        SystemParam condition = new SystemParam();
        Beans.copyProperties(reqBody, condition);
        return systemParamRepository.findAll(condition, pageable).map(entity -> {
            SystemParamPageResBody resBody = new SystemParamPageResBody();
            Beans.copyProperties(entity, resBody);
            return resBody;
        });
    }

    @Override
    @Cacheable(value = BasicConstant.PREFIX_SYSTEM_PARAM, key = "#key", unless = "#result == null")
    public String queryValue(String key) {
        List<SystemParam> list = systemParamRepository.findByKey(key);
        if (list.size() != 1) {
            throw new BusinessException("系统参数[%s]不存在或重复", key);
        }
        SystemParam entity = list.get(0);
        return SystemParam.State.ENABLED.name().equals(entity.getState()) ? entity.getValue() : null;
    }

    @Override
    @Transactional(readOnly = false)
    public void save(SystemParamReqBody reqBody) {
        int count = systemParamRepository.findByKey(reqBody.getKey()).size();
        if (count > 0) {
            throw new BusinessException("系统参数已存在，请重新输入");
        }
        SystemParam entity = new SystemParam();
        Beans.copyProperties(reqBody, entity);
        systemParamRepository.save(entity);
    }

    @Override
    @Transactional(readOnly = false)
    @CacheEvict(value = BasicConstant.PREFIX_SYSTEM_PARAM, key = "#reqBody.key")
    public void modify(SystemParamReqBody reqBody) {
        SystemParam entity =
            systemParamRepository.findById(reqBody.getId()).orElseThrow(() -> new BusinessException("系统参数不存在"));

        Beans.copyProperties(reqBody, entity);
        List<SystemParam> list = systemParamRepository.findByKey(reqBody.getKey());

        if (list.size() > 1) {
            throw new BusinessException("系统参数重复，请重新输入");
        }
        systemParamRepository.save(list.get(0));
    }

    @Override
    @Transactional(readOnly = false)
    @CacheEvict(value = BasicConstant.PREFIX_SYSTEM_PARAM, key = "#reqBody.code")
    public void delete(SystemParamReqBody reqBody) {
        SystemParam category =
            systemParamRepository.findById(reqBody.getId()).orElseThrow(() -> new BusinessException("系统参数不存在"));
        systemParamRepository.delete(category);
    }

    @Override
    @CacheEvict(value = BasicConstant.PREFIX_SYSTEM_PARAM, allEntries = true)
    public void refreshCache() {
        LOGGER.info("系统参数 [{}] 已刷新", BasicConstant.PREFIX_SYSTEM_PARAM);
    }

    @Override
    @CacheEvict(value = BasicConstant.PREFIX_SYSTEM_PARAM, key = "#key")
    public void refreshCache(String key) {
        List<SystemParam> list = systemParamRepository.findByKey(key);
        if (list.isEmpty()) {
            throw new BusinessException("系统参数不存在");
        }
        LOGGER.info("系统参数 [{}] 已刷新", BasicConstant.PREFIX_SYSTEM_PARAM + ":::" + key);
    }

}
